package com.gouda.temporary.utils;

import org.apache.http.Consts;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class XYHttpUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(XYHttpUtils.class);

	private static final String LOG_STR = "@@@@";

	/** 超时时间,单位秒 */
	private static final int TIME_OUT = 60;

	/** 超时设置: 链接超时 + 等待数据超时*/
	private static final RequestConfig REQUEST_CONFIG = RequestConfig.custom()
			                                                         .setConnectTimeout(TIME_OUT * 1000)
																	 .setConnectionRequestTimeout(TIME_OUT * 1000)
			                                                         .setSocketTimeout(TIME_OUT * 1000)
			                                                         .build();

	/**
	 * 构建定制的HttpClient
	 * @return 定制的HttpClient
	 */
	private static CloseableHttpClient buildCustomizedHttpClient() {
		return HttpClientBuilder.create().setDefaultRequestConfig(REQUEST_CONFIG).build();
	}

	/**
	 * POST操作
	 * @param url 请求的URL
	 * @param data 请求的数据
	 * @return POST返回的body数据,返回null则执行失败
	 */
	public static String doPost(String url, Map<String, String> data) {
		LOGGER.info(LOG_STR + " doPost send: URL=" + url + ", data=" + data);

		CloseableHttpClient httpClient = buildCustomizedHttpClient();
		List<NameValuePair> params 	   = new ArrayList<NameValuePair>();

		Set<String> keySet = data.keySet();
		for (String key : keySet) {
			params.add(new BasicNameValuePair(key, data.get(key)));
		}

		try {
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(new UrlEncodedFormEntity(params, Consts.UTF_8));

			CloseableHttpResponse response = httpClient.execute(httpPost);
			int 			      status   = response.getStatusLine().getStatusCode();

			if (status == HttpStatus.SC_OK) {
				String respBody = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
				LOGGER.info(LOG_STR + " doPost receive: respBody=" + respBody + ", haveSendData=" + data);
				return respBody;
			}

			LOGGER.info(LOG_STR + " doPost receive fail: HttpStatus=" + status + ", haveSendData=" + data);
			return null;
		} catch (Exception e) {
			LOGGER.warn(LOG_STR + " doPost fail, data=" + data, e);
			return null;
		} finally {
			try {
				httpClient.close();
			} catch (IOException e) {
				LOGGER.warn(LOG_STR + " httpClient close fail, data=" + data, e);
			}
		}
	}

	/**
	 * POST到用户中心,验证合法性
	 * @param url 用户中心的URL
	 * @param token 用户token
	 * @return POST返回的body数据,返回null则执行失败
	 */
	public static String doPostAuthorization(String url, String token) {
		LOGGER.info("{} authorization send: URL={}, token={}", LOG_STR, url, token);

		CloseableHttpClient httpClient = buildCustomizedHttpClient();
		try {
			HttpPost httPost = new HttpPost(url);
			httPost.setHeader("Authorization", token);
			httPost.setHeader("Content-Type", "application/json;charset=UTF-8");

			CloseableHttpResponse response = httpClient.execute(httPost);
			int 			      status   = response.getStatusLine().getStatusCode();

			if (status == HttpStatus.SC_OK) {
				String respBody = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
				LOGGER.info("{} authorization receive: body={}, token={}", LOG_STR, respBody, token);
				return respBody;
			}

			LOGGER.info("{} authorization receive fail: HttpStatus={}, token={}", LOG_STR, status, token);
			return null;
		} catch (Exception ex) {
			LOGGER.warn(LOG_STR + " authorization fail, token=" + token, ex);
			return null;
		} finally {
			try {
				httpClient.close();
			} catch (IOException e) {
				LOGGER.warn(LOG_STR + " httpClient close fail, token=" + token, e);
			}
		}
	}

	/**
	 * GET操作
	 * @param url 服务器地址
	 * @return GET返回的body数据,null则返回失败
	 */
	public static String doGet(String url) {
		LOGGER.info(LOG_STR + " doGet send: URL=" + url);

		CloseableHttpClient httpClient = buildCustomizedHttpClient();

		try {
			CloseableHttpResponse response = httpClient.execute(new HttpGet(url));
			int 			      status   = response.getStatusLine().getStatusCode();

			if (status == HttpStatus.SC_OK) {
				String respBody = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
				LOGGER.info(LOG_STR + " doGet receive: body=" + respBody + ", url=" + url);
				return respBody;
			}

			LOGGER.info(LOG_STR + " doGet receive fail: HttpStatus=" + status + ", url=" + url);
			return null;
		} catch (Exception e) {
			LOGGER.warn(LOG_STR + " doGet fail, url=" + url, e);
			return null;
		} finally {
			try {
				httpClient.close();
			} catch (IOException e) {
				LOGGER.warn(LOG_STR + " httpClient close fail, url=" + url, e);
			}
		}
	}

	/**
	 * post发送xml数据
	 * @param url 请求url
	 * @param jsonEntity 数据体
	 * @return 返回数据,null则返回失败
	 */
	public static String doPost(String url, String jsonEntity) {
		LOGGER.info(LOG_STR + " doPost send: URL=" + url + ", jsonEntity=" + jsonEntity);

		CloseableHttpClient httpClient = buildCustomizedHttpClient();
		try {
			HttpPost httpPost = new HttpPost(url);

			//得指明使用UTF-8编码，否则到API服务器XML的中文不能被成功识别
			StringEntity postEntity = new StringEntity(jsonEntity, Consts.UTF_8);
			httpPost.addHeader("Content-Type", "application/json;charset=UTF-8");
			httpPost.setEntity(postEntity);

			CloseableHttpResponse response = httpClient.execute(httpPost);
			int 			      status   = response.getStatusLine().getStatusCode();
			if (status == HttpStatus.SC_OK) {
				String respBody = EntityUtils.toString(response.getEntity(), Consts.UTF_8);
				LOGGER.info(LOG_STR + " doPost receive: respBody=" + respBody +", jsonEntity=" + jsonEntity);
				return respBody;
			}

			LOGGER.info(LOG_STR + " doPost receive fail: HttpStatus=" + status + ", jsonEntity=" + jsonEntity);
			return null;
		} catch (Exception e) {
			LOGGER.warn(LOG_STR + " doPost fail, URL=" + url + ", jsonEntity=" + jsonEntity);
			return null;
		}
	}
}
